package ui

import (
	"catlib/lib/ui/porterduff"
	"image"
	"image/color"
	"image/png"
	"os"
)

type rgba struct {
	APIBaseStruct
	NRGBA *image.NRGBA          // 继承官方库底层
	Blend porterduff.ColorBlend // 混合函数
}

// New 创建
func (Rgba *rgba) New(width int, height int, Blend porterduff.ColorBlend) {
	defer Rgba.recover() // 错误拦截
	Rgba.NRGBA = image.NewNRGBA(image.Rect(0, 0, width, height))
	Rgba.Blend = Blend
}

// ImagesGet 得到图片
func (Rgba *rgba) ImagesGet() *image.NRGBA {
	return Rgba.NRGBA
}

// ImagesExport 导出图片
func (Rgba *rgba) ImagesExport(name string) error {
	defer Rgba.recover() // 错误拦截
	f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	// 创建图片对象
	return png.Encode(f, Rgba.ImagesGet())
}

// DrawPixel 画像素
func (Rgba *rgba) DrawPixel(x, y int, c color.Color) {
	defer Rgba.recover() // 错误拦截
	nrgba := Rgba.NRGBA
	rectMax := nrgba.Rect.Max
	if x > rectMax.X || y > rectMax.Y {
		return
	}
	i := nrgba.PixOffset(x, y)
	s := nrgba.Pix[i : i+4]
	// 根据参数合并颜色
	R, G, B, A := c.RGBA()
	s[0] = uint8(R)
	s[1] = uint8(G)
	s[2] = uint8(B)
	s[3] = uint8(A)
}

// DrawColor 画颜色
func (Rgba *rgba) DrawColor(x, y int, c Color, isCover bool) {
	defer Rgba.recover() // 错误拦截
	// 限制绘图范围
	point := Rgba.NRGBA.Rect.Max
	if x > point.X {
		x = point.X
	}
	if y > point.Y {
		y = point.Y
	}
	max := c.ImagesGet().Rect.Max
	width, height := max.X, max.Y
	// 限制绘图大小
	if width > point.X {
		width = point.X
	}
	if height > point.Y {
		height = point.Y
	}
	// 大写不可为空
	pix := c.ImagesGet()
	if isCover {
		for outW, inW := x, 0; outW < width; outW++ {
			for outH, inH := y, 0; outH < height; outH++ {
				in := pix.PixOffset(inW, inH)
				out := Rgba.NRGBA.PixOffset(outW, outH)
				inPix := pix.Pix[in : in+4 : in+4]
				outPix := Rgba.NRGBA.Pix[out : out+4 : out+4]
				outPix[0] = inPix[0]
				outPix[1] = inPix[1]
				outPix[2] = inPix[2]
				outPix[3] = inPix[3]
				inH++
			}
			inW++
		}
	} else {
		for outW, inW := x, 0; outW < width; outW++ {
			for outH, inH := y, 0; outH < height; outH++ {
				// 计算偏移
				in := pix.PixOffset(inW, inH)
				inPix := pix.Pix[in : in+4 : in+4]
				out := Rgba.NRGBA.PixOffset(outW, outH)
				outPix := Rgba.NRGBA.Pix[out : out+4 : out+4]
				// 混合颜色
				r, g, b, a := Rgba.Blend(
					float64(outPix[0])/255, float64(outPix[1])/255, float64(outPix[2])/255, float64(outPix[3])/255,
					float64(inPix[0])/255, float64(inPix[1])/255, float64(inPix[2])/255, float64(inPix[3])/255,
				)
				// 赋值
				outPix[0] = uint8(r * 255)
				outPix[1] = uint8(g * 255)
				outPix[2] = uint8(b * 255)
				outPix[3] = uint8(a * 255)
				inH++
			}
			inW++
		}
	}
}

// Tailoring 局部剪裁
func (Rgba *rgba) Tailoring(x, y, width, height int) (c Color) {
	defer Rgba.recover() // 错误拦截
	// 限制绘图范围
	point := Rgba.NRGBA.Rect.Max
	if x > point.X {
		x = point.X
	}
	if y > point.Y {
		y = point.Y
	}
	// 限制绘图大小
	if width > point.X {
		width = point.X
	}
	if height > point.Y {
		height = point.Y
	}
	// 大写不可为空
	if width-x < 1 || height-y < 1 {
		return c
	}
	// 循环绘制数据
	c.New(width-x, height-y, Rgba.Blend)
	pix := c.ImagesGet()
	for outW, inW := x, 0; outW < width; outW++ {
		for outH, inH := y, 0; outH < height; outH++ {
			in := Rgba.NRGBA.PixOffset(inW, inH)
			out := pix.PixOffset(outW, outH)
			inPix := Rgba.NRGBA.Pix[in : in+4 : in+4]
			outPix := pix.Pix[out : out+4 : out+4]
			outPix[0] = inPix[0]
			outPix[1] = inPix[1]
			outPix[2] = inPix[2]
			outPix[3] = inPix[3]
			inH++
		}
		inW++
	}
	return c
}

// NewColor 创建颜色对象
func NewColor() Color {
	return &rgba{}
}

// NewColorNRGBA 从 NRGBA 创建对象
func NewColorNRGBA(NRGBA *image.NRGBA, Blend porterduff.ColorBlend) Color {
	return &rgba{NRGBA: NRGBA, Blend: Blend}
}
